package startupcompanymanager2012;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import javax.swing.JOptionPane;

public class Game implements Serializable {

    private final int COSTS_PER_LINE = 1;
    private String title;
    boolean releaseStatus;
    private int score, completedLines, totalLines, bugs, status;
    private double price = 0, cost = 0.00;
    private Calendar begin, release;
    private Genre genre;
    private Type type;
    private Focus focus;
    private Language language;
    private Platform platform;
    private Developer dev;
    private int usedTime = 0, maxBugs = 0, onTheMarket = 0;
    private boolean writing, debugging, done;
    public double bonusFactor;
    public static ArrayList<Genre> genres = new ArrayList<Genre>();
    public static ArrayList<Type> types = new ArrayList<Type>();
    public static ArrayList<Focus> focuses = new ArrayList<Focus>();
    public static ArrayList<Platform> platforms = new ArrayList<Platform>();
    public static ArrayList<Language> languages = new ArrayList<Language>();

    public Game(String name, int totLines, Genre g, Type t, Focus f, Language l, Platform p, Developer d, Double cost) {
        /*
         * Constructor with all of the propierties that have been selected for the game
         */
        this.title = name;
        this.completedLines = 0;
        this.totalLines = totLines;
        this.bugs = 0;
        this.genre = g;
        this.type = t;
        this.focus = f;
        this.language = l;
        this.platform = p;
        this.dev = d;
        this.cost = cost;
        this.bonusFactor = 1.00;
        this.price = calculatePrice() + g.getCost();
        this.score = 0;
        this.release = Calendar.getInstance();  // to be changed!
        this.begin = Calendar.getInstance(); // to be changed
        this.releaseStatus = false;
        //calculates the maxbugs beforehand for statistics
        maxBugs = (int) (totalLines * ((Developer.BUGS_PER_LINE - Developer.BUGS_PER_LINE * (dev.getBugsPerLine() / 100))));
        writing = true;
        debugging = false;
        done = false;
        dev.setWorking(true);
    }

    public void elaborate(int days) {
        /*
         * works on the game for a specified amount of days,
         * if the days are way tomany in relation to the lines remaining it opens a
         * JOptionPanel notification. The lines may exceed the totallines for a small amount.
         */
        if ((completedLines + days * (Developer.getMAX_LINES_PER_DAY() * ((dev.getSpeed() / 100.00))))
                <= (totalLines + (Developer.getMAX_LINES_PER_DAY() * (dev.getSpeed() / 100.00)))) {
            usedTime += days;
            projectCalendar.addDays(days);
            completedLines += days * (Developer.getMAX_LINES_PER_DAY() * ((dev.getSpeed() / 100.00)));
            bugs = (int) (completedLines * ((Developer.BUGS_PER_LINE - Developer.BUGS_PER_LINE * (dev.getBugsPerLine() / 100))));
        } else {

            JOptionPane.showMessageDialog(null, "Your entered too many days in comparison"
                    + "\nto the amount of lines you need to write");
        }
        if (completedLines >= totalLines) {
            /*
             * if the completed lines exceed the totallines they are set back 
             * to the amount of totallines. The process is set to debugging mode.
             */
            completedLines = totalLines;
            setWriting(false);
            setDebugging(true);

        }
    }

    public void removeBugs(int days) {
        /*
         * Method for removing bugs when lines are complete
         */
        bugs = bugs - (int) (days * ((Developer.BUGS_PER_LINE * 1000.00) * (dev.getBugsPerLine() / 100.00)));
        projectCalendar.addDays(days);
        //finishes the product when bugs are 0 or below.
        if (bugs <= 0) {
            bugs = 0;
            setWriting(true);
            setDebugging(false);
        }
        usedTime += days;
    }

    public double calculatePrice() {
        //TODO: redo pricecalculation when sale system is available

        double cost = (COSTS_PER_LINE * this.totalLines);
        double reducedCost = cost * (this.getStatus()); //(You cant get the full price for an unfinished product);
        return reducedCost;  //this.getStatus()/100*100 would be right to have cents
    }

    public void checkGame() {
        /*
         * checks if the game is completed or not. If so, then it resets the boolean-values
         * updates the devs experience and other stats
         */
        if (completedLines == totalLines && bugs <= 0) {
            StartupCompanyManager2012gameWorker.updateStats();
            bugs = 0;
            StartupCompanyManager2012View.updateBudgetLabel();
            dev.setDaysWorked(usedTime);
            dev.setGamesDeveloped(1);
            calculateScore();
            dev.setExperiencePoints(score / 100);
            dev.setWorking(false);
            StartupCompanyManager2012gameWorker.buttonWork = true;
            StartupCompanyManager2012gameWorker.buttonDebug = false;
            StartupCompanyManager2012gameWorker.bonusReady = false;
            StartupCompanyManager2012gameWorker.checkBonusAvailable();
            this.done = true;
            JOptionPane.showMessageDialog(null, "You have successfully finished developing this game!"
                    + "\n " + title + " reached a score of " + score + " Points!");
        }
    }
    //if game is more then 66% finished it can be released, for later on

    public void release() {
        if (this.getStatus() > 66) { //66% at least to be released
            this.releaseStatus = true;
        }
    }
    //calculates the score of a game, important for sales later on

    public void calculateScore() {

        score = (int) ((((totalLines + (int) price + maxBugs * 10) / (maxBugs / 10 + (200 - usedTime) / 100))) * bonusFactor);
    }

    @Override
    public String toString() {
        return title;
    }
    //GETTERS

    public int getMaxBugs() {
        maxBugs = (int) (totalLines * ((Developer.BUGS_PER_LINE - Developer.BUGS_PER_LINE * (dev.getBugsPerLine() / 100))));

        return maxBugs;
    }

    public int getCompletedLines() {
        return completedLines;
    }

    public int getUsedTime() {
        return usedTime;
    }

    public int getStatus() {
        status = (int) (100.0 * ((completedLines - ((maxBugs * bugs))) / (double) (totalLines - maxBugs * bugs)));
        return status;
    }

    public int getBugs() {
        return bugs;
    }

    public String getReleaseDate() {
        //to be changed
        String str = this.release.get(5) + "." + this.release.get(2) + "." + this.release.get(1);
        return str;
    }

    public String getTitle() {
        return title;
    }

    public String getBeginDate() {
        //to be changed
        String str = this.begin.get(5) + "." + this.begin.get(2) + "." + this.begin.get(1);
        return str;
    }

    public String getGenre() {
        return genre.getName();
    }

    public String getPlatform() {
        return platform.getName();
    }

    public String getLanguage() {
        return language.getName();
    }

    public double getPrice() {
        return price;
    }

    public int getScore() {
        return score;
    }

    public String getFocus() {
        return focus.getName();
    }

    public String getType() {
        return type.getName();
    }

    public int getTotalLines() {
        return totalLines;
    }

    public String getDevName() {
        return dev.getName();

    }

    public Developer getDev() {
        return dev;
    }

    public int getOnTheMarket() {
        return onTheMarket;
    }

    public double getCost() {
        return cost;
    }
    //Boolean GETTERS

    public boolean isDone() {
        return done;
    }

    public boolean isDebugging() {
        return debugging;
    }

    public boolean isWriting() {
        return writing;
    }
    //SETTERS

    public void setPrice(double price) {
        this.price = price;
    }

    public void setOnTheMarket(int onTheMarket) {
        this.onTheMarket = onTheMarket;
    }

    public void setDone(boolean d) {
        this.done = d;
    }

    public void setDebugging(boolean debugging) {
        this.debugging = debugging;
    }

    public void setWriting(boolean writing) {
        this.writing = writing;
    }
}
